package com.hsmpay.mobile.service.trans.impl;

import com.hsmpay.common.pojo.BasePojo;
import com.hsmpay.common.service.impl.BaseServiceSupport;
import com.hsmpay.common.util.NumberUtil;
import com.hsmpay.common.util.system.Constant;
import com.hsmpay.mobile.dao.trans.SSBindCardsDao;
import com.hsmpay.mobile.dao.trans.UserNocardpayLogDao;
import com.hsmpay.mobile.dao.trans.UserVerifycardsLogDao;
import com.hsmpay.mobile.pojo.trans.SSBindCards;
import com.hsmpay.mobile.pojo.trans.SSBindCardsExample;
import com.hsmpay.mobile.pojo.trans.UserNocardpayLog;
import com.hsmpay.mobile.pojo.trans.UserVerifycardsLog;
import com.hsmpay.mobile.pojo.trans.UserVerifycardsLogExample;
import com.hsmpay.mobile.pojo.user.SendmsgLog;
import com.hsmpay.mobile.service.trans.SSBindCardsService;
import com.hsmpay.mobile.service.user.VerifiService;
import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.Identities;
import com.hsmpay.utils.JSONStringBuilder;
import com.hsmpay.utils.MD5Util;
import com.test.HttpClientUtil;
import com.test.RSAUtils;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by zhy on 16/3/28.
 *
 * 用户绑定信用卡实现类
 */
@Service("ssBindCardsService")
public class SSBindCardsServiceImpl<Entity extends SSBindCards,Query extends Object> extends BaseServiceSupport<Entity,Query> implements SSBindCardsService<Entity,Query>{
	private Logger log = Logger.getLogger(this.getClass());
	
	@Resource(name = "ssBindCardsDao")
    private SSBindCardsDao<SSBindCards,Long> bindCardsDao;
    
    @Resource(name = "userVerifycardsLogDao")
    private  UserVerifycardsLogDao userVerifycardsLogDao;
    
    @Resource(name = "userNocardpayLogDao")
    private  UserNocardpayLogDao userNocardpayLogDao;
    @Resource(name = "verifiService")
    private VerifiService<BasePojo, Long> verifiService;
    /**
     * 插入用户绑定信用卡
     * @return
     * @throws SQLException
     */
    public Long insertSSBindCards(SSBindCards bindCards) throws Exception {

        return bindCardsDao.insertEntity(bindCards);
    }
    @Override
	public int updateByExampleSelective(SSBindCards record, SSBindCardsExample example) {
		return bindCardsDao.updateByExampleSelective(record, example);
	}

    /**
     * 查询用户绑定信用卡列表
     * @return
     * @throws SQLException
     */
    public List<SSBindCards> searchSSBindCards(Long userId) throws SQLException {
        SSBindCards bindCards = new SSBindCards();
        bindCards.setUserId(userId);
        return bindCardsDao.searchEntityList(bindCards);
    }

	/**
	 * 信用卡鉴权
	 * @param userVerifycardsLog
	 * @param roleId
	 * @param terminalTypeId
     * @return
     */
	public Map<String,Object> authCard(UserVerifycardsLog userVerifycardsLog,Long roleId,Long terminalTypeId) {
		Map<String,Object> resultMap  = new HashMap<String,Object>();
		TreeMap<String,String> parameterMap = new TreeMap<String,String>();
		String companyid = Constant.getAttribute("COMPANY_ID");
		String uinpayKey = Constant.getAttribute("UINPAY_KEY");
		String requestId = Identities.toCurrentTime();
		String resultcode = "";
		parameterMap.put("companyid", companyid); // 企业账户号
		parameterMap.put("requestid", requestId); // 请求流水号
		parameterMap.put("cardtype", "2");   // 卡折类型
		parameterMap.put("accno", userVerifycardsLog.getCardnumber());         // 账户号
		parameterMap.put("accname", userVerifycardsLog.getCardholder());    // 账户名
		parameterMap.put("idcardtype", "01");// 证件类型  01身份证
		parameterMap.put("idcard", userVerifycardsLog.getIdcard());// 证件号
		parameterMap.put("phone", userVerifycardsLog.getPhonenumber());//预留手机号
		parameterMap.put("orderid", requestId);//客户订单号  20
		parameterMap.put("transtime", getCurrentTimeNumber());//交易时间  年月日时 如：20160108100000
		
		// 加签过程
		parameterMap.put("sign", getSign(parameterMap));// 签名

		String paramStr = JSONStringBuilder.getAjaxString(parameterMap);
		log.info("尤银鉴权-发送的报文明文为: " + paramStr);
		try {
			paramStr = DesUtil.encryptThreeDES(paramStr.getBytes("UTF-8"),uinpayKey);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		paramStr =  companyid+ "," + paramStr;
		log.info("尤银鉴权-发送的报文加密结果为: " + paramStr);
		// 判断是否已经存在   存在直接返回 不存在则调用鉴权接口
			if(isAuth(userVerifycardsLog)){//检查是否存在
				String result = HttpClientUtil.httpPostWithJSON(Constant.getAttribute("AUTH_CARD_URL"), paramStr);
	
				result = result.split(",")[1];
				log.info("尤银鉴权-返回的报文加密结果为: " + result);
				result = decode3DES(result, uinpayKey);
				log.info("尤银鉴权-返回的报文明文结果为: " + result);
				boolean res = Verify(result);
				if (res) {//验签成功
					// 解析报文
					JSONObject jsonObject = JSONObject.fromObject(result);
					resultcode = jsonObject.getString("resultcode");
					//resultcode = "0000";
					String errorcode = "";
					String errormsg = "";
					errorcode = jsonObject.getString("errorcode");
					errormsg = jsonObject.getString("errormsg");
					if (resultcode.equals("0000")) {// 调用短信服务
						sendInfoToUser(userVerifycardsLog.getPhonenumber(), roleId, userVerifycardsLog.getUserid(),terminalTypeId);
					} else if (resultcode.equals("0001")) {// 处理中
						result = query(companyid, requestId, uinpayKey, Constant.getAttribute("AUTH_CARD_QUERY_URL"));
						jsonObject = JSONObject.fromObject(result);
						resultcode = jsonObject.getString("resultcode");
						errorcode = jsonObject.getString("errorcode");
						errormsg = jsonObject.getString("errormsg");
						if (resultcode.equals("0000")) // 调用短信服务
							sendInfoToUser(userVerifycardsLog.getPhonenumber(), roleId, userVerifycardsLog.getUserid(),terminalTypeId);
					}
				userVerifycardsLog.setErrorcode(errorcode);
				userVerifycardsLog.setErrormsg(errormsg);
				userVerifycardsLog.setResulttime(new Date());// XXX 取返回日期
				userVerifycardsLog.setResultcode(resultcode);
				userVerifycardsLog.setOrderid(requestId);
				userVerifycardsLog.setStatus(resultcode.equals("0000")?(short)1:(short)2);
				userVerifycardsLog.setCreatetime(new Date());
				userVerifycardsLogDao.insert(userVerifycardsLog);
				if(errormsg.isEmpty()) errormsg="程序异常,请联系客服!";
				resultMap.put("reqCode", resultcode);
				resultMap.put("reqMsg", resultcode.equals("0000")?"鉴权通过":errormsg);
			}else{
				resultMap.put("reqCode","9999");
				resultMap.put("reqMsg","程序异常,请联系客服!");
				log.error("尤银鉴权-报文验签失败: " + res);
			}
		}else{
			sendInfoToUser(userVerifycardsLog.getPhonenumber(), roleId, userVerifycardsLog.getUserid(), terminalTypeId);
			resultMap.put("reqCode", "0000");
			resultMap.put("reqMsg", "鉴权通过!");
		}
		return resultMap;
	}
	
	public String query(String companyid,String orderid,String uinpayKey,String url){
		
		TreeMap<String,String> parameterMap = new TreeMap<String,String>();

		parameterMap.put("companyid", companyid); // 企业账户号

		parameterMap.put("orderid", orderid);//客户订单号  20

		//加签过程
		parameterMap.put("sign", getSign(parameterMap));//签名

		String paramStr = JSONStringBuilder.getAjaxString(parameterMap);
		log.info("鉴权查询-发送的报文明文为: " + paramStr);
		try {
			paramStr = DesUtil.encryptThreeDES(paramStr.getBytes("UTF-8"), uinpayKey);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		paramStr = companyid + "," + paramStr;
		log.info("鉴权查询-发送的报文加密结果为: " + paramStr);
		String result = null;
		try {
			
			for (int i = 0; i < 5; i++) {
				Thread.sleep(1000);
				result = HttpClientUtil.httpPostWithJSON(url, paramStr);
				result = result.split(",")[1];
				log.info("鉴权查询-返回的报文加密结果为: " + result);
				result = decode3DES(result,uinpayKey);
				log.info("鉴权查询-返回的报文明文结果为: " + result);
				boolean b = Verify(result);
				log.info("验签状态 ：" + b);
				//if(!b)return "";
				JSONObject resultJson = JSONObject.fromObject(result);
				String resultcode = resultJson.getString("resultcode");
				if(resultcode.equals("0000")){
					break;
				}
				
			}
			return result;
		} catch (InterruptedException e) {
		
			e.printStackTrace();
		}
		
		 return null;
	}
	/**
	 * 支付并绑定接口
	 * 1.验证短信  正确  错误
	 * 2.调用支付口
	 * 3.解析入库
	 * 4.同步到用户卡列表
	 */
	@Override
	public Map bindBankCard(UserNocardpayLog userNocardpayLog,String code) {
		Map<String,Object> resultMap  = new HashMap<String,Object>();
		String companyid = Constant.getAttribute("COMPANY_ID");
		String uinpayKey = Constant.getAttribute("UINPAY_KEY");
		String phonenumber = userNocardpayLog.getPhonenumber();
		String orderid = Identities.toCurrentTime();
		TreeMap<String,String> parameterMap = new TreeMap<String,String>();
		parameterMap.put("amount", String.valueOf(userNocardpayLog.getTransamount()));
		parameterMap.put("cardno", userNocardpayLog.getCardnumber());
		parameterMap.put("idcardtype", "01");
		parameterMap.put("idcard", userNocardpayLog.getIdcard());
		parameterMap.put("owner", userNocardpayLog.getCardholder());
		parameterMap.put("currency", "156");
		parameterMap.put("cvv2", userNocardpayLog.getCvv2());
		parameterMap.put("usercode", String.valueOf(System.currentTimeMillis()));
		//parameterMap.put("identitytype", "01");//
		parameterMap.put("companyid", companyid);
		parameterMap.put("orderid", orderid);
		parameterMap.put("phone", phonenumber);
		parameterMap.put("productcode", userNocardpayLog.getProductcode());
		parameterMap.put("productdesc", userNocardpayLog.getProductdesc());
		parameterMap.put("productname", userNocardpayLog.getProductname());
		parameterMap.put("transtime", String.valueOf(System.currentTimeMillis()));
		parameterMap.put("userip", userNocardpayLog.getUserip());
		parameterMap.put("validthru", userNocardpayLog.getDuedate());
		parameterMap.put("sign", getSign(parameterMap));

		String paramStr = JSONStringBuilder.getAjaxString(parameterMap);
		log.info("尤银支付-发送的报文明文为: " + paramStr);
		try {
		   paramStr = DesUtil.encryptThreeDES(paramStr.getBytes("UTF-8"), uinpayKey);
		   boolean b = verifiService.verifiCode(VerifiService.CODETYPE_CARDBIND, 1, code, phonenumber, null);
		   if(!b){
			   resultMap.put("reqCode", "9999");
			   resultMap.put("reqMsg", "验证码错误!");
			   userNocardpayLog.setOrderid(orderid);
			   userNocardpayLog.setStatus("9999");
			   userNocardpayLog.setErrormsg("验证码错误!");
			   userNocardpayLogDao.insert(userNocardpayLog);
			   return resultMap;
		   }
			
		   
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		paramStr = companyid + "," + paramStr;
		log.info("尤银支付-发送的报文加密结果为: " + paramStr);
		String result = HttpClientUtil.httpPostWithJSON(Constant.getAttribute("UIN_PAY_URL"), paramStr);

		result = result.split(",")[1];
		log.info("尤银支付-返回的报文加密结果为: " + result);
		
		result = decode3DES(result,uinpayKey);
		log.info("尤银支付-返回的报文明文结果为: " + result);
		boolean res = Verify(result);
		if(res){
			JSONObject jsonObject = JSONObject.fromObject(result);
			String bindid = jsonObject.getString("bindid");
			String errorcode = jsonObject.getString("errorcode");
			String errormsg = jsonObject.getString("errormsg");
			String status = jsonObject.getString("status");
			String uyorderid = jsonObject.getString("uyorderid");
			resultMap.put("reqCode", status);
			resultMap.put("reqMsg", errormsg);
			userNocardpayLog.setErrorcode(errorcode);
			userNocardpayLog.setErrormsg(errormsg);
			userNocardpayLog.setStatus(status.equals("0000")?"1":"2");
			userNocardpayLog.setUyderid(uyorderid);
			userNocardpayLog.setBindid(bindid);
		}else{
			resultMap.put("reqCode","9999");
			resultMap.put("reqMsg","程序异常,验签失败!");
			log.error("尤银支付-报文验签失败: " + res);
		}
		log.info("验签的结果为: " + res);
		userNocardpayLog.setOrderid(orderid);
		userNocardpayLogDao.insert(userNocardpayLog);
		
		return resultMap;
	}

	/**
	 * 记录秒到绑卡时的消费信息
	 * @param userNocardpayLog
	 */
	public void insertUserNocardpayLog(UserNocardpayLog userNocardpayLog) {
		userNocardpayLogDao.insert(userNocardpayLog);
	}

	/**
	 * 判断信用卡是否需要进行鉴权
	 * @param userVerifycardsLog
	 * @return 返回码0000成功
     */
	public boolean isAuth(UserVerifycardsLog userVerifycardsLog){
		Long userid = userVerifycardsLog.getUserid();
		String idcard = userVerifycardsLog.getIdcard();
		String phonenumber = userVerifycardsLog.getPhonenumber();
		String userName = userVerifycardsLog.getCardholder();//帐户名
		String cardnumber = userVerifycardsLog.getCardnumber();
		UserVerifycardsLogExample example = new UserVerifycardsLogExample();
		example.createCriteria().andUseridEqualTo(userid).andIdcardEqualTo(idcard).andPhonenumberEqualTo(phonenumber)
		.andCardholderEqualTo(userName).andCardnumberEqualTo(cardnumber).andResultcodeEqualTo("0000");
		int i = userVerifycardsLogDao.countByExample(example);
		return i==0?true:false;
	}
	/**
	 * 发送短信
	 */
	public void sendInfoToUser(String mobile,Long roleId,Long userId,Long terminalTypeId){
		try {
			String code = NumberUtil.getRegisterMobileCode();
			SendmsgLog sendmsgLog = new SendmsgLog();
			sendmsgLog.setCode(code);
			sendmsgLog.setCreateDate(new Date());
			sendmsgLog.setCodeType(5);// 5 鉴权  2 绑定银行
			sendmsgLog.setMobile(mobile);
			sendmsgLog.setRoleId(roleId);//5
			sendmsgLog.setTerminalTypeId(terminalTypeId);
			sendmsgLog.setUserId(userId);
			//sendmsgLog.setUuId(uuid);
			String content = "尊敬的客户您好,您的手机验证码为: [" + code + "],感谢您的支持！";
			verifiService.sendMobileCode(mobile, code, sendmsgLog,content);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 返回当前时间的数字
	 *
	 * @return 返回当前时间的数字
	 */
	public static String getCurrentTimeNumber() {
		return new SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date());
	}
	/**
	 * 
	 * @param parameterMap
	 * @return
	 */
	private String getSign(TreeMap<String, String> parameterMap) {
		String path = this.getClass().getResource("/").getFile().toString();
		path = path + "cert/uinpay/";
		RSAUtils rsaUtils = new RSAUtils();
		rsaUtils.initKey(path + "pkcs8_rsa_private_key.pem", path + "uinpay_abc_public_key_2048.pem");
		String sign = treeMapToString(parameterMap);
		String result = rsaUtils.sign(sign);
		return result;
	}
	

	/**
	 * 将map拼接成所需的字符串
	 * @param treeMap
	 * @return
     */
	public String treeMapToString(TreeMap<String,String> treeMap){
		StringBuffer buffer = new StringBuffer(206);
		Iterator<String> iterator = treeMap.keySet().iterator();
		String key = null, value = null;
		while(iterator.hasNext()){
			key = iterator.next();
			value = treeMap.get(key);
			buffer.append(key).append("=");
			if (null != value){
				buffer.append(value);
			}
		}
		return buffer.toString();
	}
	/**
	 * 验签 报文
	 * @param jsonStr
	 * @return boolean 
	 */
	public boolean Verify(String jsonStr){
		TreeMap<String, String> treeMap = new TreeMap<String,String>();

		JSONObject json = JSONObject.fromObject(jsonStr);
		for(Object k : json.keySet()){
			String v = (String) json.get(k);
			if (!"sign".equals(k.toString())){
				treeMap.put(k.toString(), v);
			}
		}
		//验签的字符串
		String plaintext = treeMapToString(treeMap);
		System.out.println("验签的字符串为: " + plaintext);
		//验签的签
		String sign = (String) json.get("sign");
		log.info("验签的字符串为: " + sign);
		String path = this.getClass().getResource("/").getFile().toString();
		path = path + "cert/uinpay/";
		RSAUtils rsaUtils = new RSAUtils();
		rsaUtils.initKey(path + "pkcs8_rsa_private_key.pem", path + "uinpay_abc_public_key_2048.pem");
		return rsaUtils.verify(plaintext ,sign);
	}
	/**
	 * 3DES解密
	 * @param dataS 待解密数
	 * @param keys 密钥
	 * @return byte[] 解密数据
	 */
	public String decode3DES(String dataS, String keys){
		String result="";
		try {
			byte[] data=DesUtil.hexStringToByte(dataS);
			byte[] key=DesUtil.hexStringToByte(keys);
			Cipher cipher = Cipher.getInstance("DESede");
			DESedeKeySpec dks = new DESedeKeySpec(key);
			SecretKey k = SecretKeyFactory.getInstance("DESede")
					.generateSecret(dks);
			cipher.init(Cipher.DECRYPT_MODE, k);
			byte[] src = cipher.doFinal(data);
			result = new String(src, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("" + e);
		}
		return result;
	}

	/**
	 * 诺正通信用卡鉴权
	 * @param userVerifycardsLog
	 * @param roleId
	 * @param terminalTypeId
	 * @return
	 */
	public Map<String,Object> NZTAuthCard(UserVerifycardsLog userVerifycardsLog,Long roleId,Long terminalTypeId) {
		Map<String,Object> resultMap  = new HashMap<String,Object>();
		// 判断是否已经存在 存在直接返回 不存在则调用鉴权接口
		if(isAuth(userVerifycardsLog)){//检查是否存在
			String mallId = Constant.getAttribute("NZT_MALL_ID"); //商家ID
			String appKey = Constant.getAttribute("NZT_APP_KEY"); //密钥
			String realName = userVerifycardsLog.getCardholder(); //需要认证的用户姓名
			String idCard = userVerifycardsLog.getIdcard().toLowerCase(); //需要认证的身份证号,如果最后一位是X,请转换成x
			String cardNum = userVerifycardsLog.getCardnumber(); //需要认证的银行卡号
			String bankPreMobile = userVerifycardsLog.getPhonenumber(); //银行预留手机号
			String tm = String.valueOf(new Date().getTime()); //当前时间戳
			String requestId = Identities.toCurrentTime();

			//计算签名
			String sign = MD5Util.md5(mallId + realName + cardNum + tm + appKey);
			//拼接get请求参数
			String param = "mall_id="+mallId +"&"+ "realname="+realName +"&"+ "idcard="+idCard +"&"+
					"cardnum="+cardNum +"&"+ "bankPreMobile="+bankPreMobile + "&" + "tm="+tm +"&"+ "sign="+sign;
			log.debug("诺正通信用卡鉴权-请求参数: " + param);
			String result = HttpClientUtil.sendGet(Constant.getAttribute("NZT_AUTH_CARD_URL"), param);
			log.debug("诺正通信用卡鉴权-响应参数: " + result);

			// 解析报文
			JSONObject resultJson = JSONObject.fromObject(result);
			String resultStatus = resultJson.getString("status");
			String resultData = resultJson.getString("data");
			JSONObject dataJson = JSONObject.fromObject(resultData);
			String code = dataJson.getString("code");
			String message = dataJson.getString("message");

			String resultcode = "";
			if(resultStatus.equals("2001") && code.equals("1000")){
				resultcode = "0000";
			}else {
				resultcode = code;
			}
			// 调用短信服务
			if (code.equals("0000")){
				sendInfoToUser(userVerifycardsLog.getPhonenumber(), roleId, userVerifycardsLog.getUserid(),terminalTypeId);
			}

			userVerifycardsLog.setErrorcode(code);
			userVerifycardsLog.setErrormsg(message);
			userVerifycardsLog.setResulttime(new Date());
			userVerifycardsLog.setResultcode(resultcode);
			userVerifycardsLog.setStatus(resultcode.equals("0000")?(short)1:(short)0);
			userVerifycardsLog.setCreatetime(new Date());
			userVerifycardsLog.setOrderid(requestId);
			userVerifycardsLogDao.insert(userVerifycardsLog);
			if(message.isEmpty()){
				message="程序异常,请联系客服!";
			}
			resultMap.put("reqCode", resultcode);
			resultMap.put("reqMsg", resultcode.equals("0000")?"鉴权通过":message);
		}else{
			sendInfoToUser(userVerifycardsLog.getPhonenumber(), roleId, userVerifycardsLog.getUserid(), terminalTypeId);
			resultMap.put("reqCode", "0000");
			resultMap.put("reqMsg", "鉴权通过!");
		}
		return resultMap;
	}
	@Override
	public List<SSBindCards> selectBindCardsListByUserId(Long userId) {
		return bindCardsDao.selectBindCardsListByUserId(userId);
	}
	
}
